<?php

/**
 * @category   Mediad
 * @package    Mediad2_Mapper
 */
abstract class Mediad2_Mapper_Abstract
{
	/**
	 * meta data 
	 * @var array
	 */
	protected $metadata = array();
	
	/**
	 * get metadata
	 * @return array
	 */
	public function getMetadata()
	{
		return $this->metadata;
	}
	
	/**
	 * set metadata
	 * @param array $metadata
	 */
	public function setMetadata(array $metadata)
	{
		$this->metadata = $metadata;
		return $this;
	}
	
	/**
	 * primary key object
	 * @var mixed
	 */
	protected $pk;
	
	/**
	 * set pk
	 * @param mixed
	 * @return Mediad2_Model_Abstract
	 */
	public function setPk($pk)
	{
		$this->pk = $pk;
		return $this;
	}
	
	/**
	 * get pk
	 * @return mixed
	 */
	public function getPk()
	{
		return $this->pk;
	}
	
	/**
	 * DAO object
	 *
	 * @var Mediad2_Dao_Abstract
	 */
	protected $dao;
	
	/**
	 * Constructor.
	 *
	 * @return void
	 */
	public function __construct()
	{
		$this->init();
	}
	
	/**
	 * Initialize object
	 *
	 * Called from {@link __construct()} as final step of object instantiation.
	 *
	 * @return void
	 */
	public function init()
	{
	}
	
	/**
	 * set dao
	 * 
	 * @param string $dao
	 * @throws Exception
	 * @return Mediad2_Mapper_Abstract
	 */
	public function setDao($dao)
	{		
		if (is_string($dao)) {
			$dao = new $dao();
		}
		if (!$dao instanceof Zend_Db_Table_Abstract) {
			throw new Exception('Invalid table data gateway provided!');
		}
		$this->dao = $dao;
		
		//设置主键数据
		$primary = $this->dao->info(Zend_Db_Table_Abstract::PRIMARY);
		$this->setPk($primary); //默认为1，有可能存在1个以上的主键
		
		//设置metadata
		$metadata = $this->dao->info(Zend_Db_Table_Abstract::METADATA);
		$this->setMetadata($metadata);
		
		return $this;
	}
	
	/**
	 * return dao
	 *
	 * @return Mediad2_Dao_Abstract
	 */
	public function getDao ()
	{
		return $this->dao;
	}
	
	
	/**
	 * insert a new row
	 * @param array $data
	 * @return mixed The primary key of the row inserted.
	 * @throws Mediad2_Mapper_Exception 
	 */
	public function insert(array $data)
	{
		$dao = $this->getDao();

		//清除掉不属于本表的数据
		$fields = $dao->info(Zend_Db_Table_Abstract::COLS);
		foreach ($data as $key => $value) {
			if (! in_array($key, $fields)) {
				unset($data[$key]);
			}
		}
		
		return $dao->insert($data);
	}
	
	/**
	 * update by primary key
	 * 
	 * @param array $data
	 * @return int  The number of rows updated.
	 */
	public function update(array $data)
	{
		$dao = $this->getDao();
		$adapter = $dao ->getAdapter();
		$selector = $dao->select();
		
		//清除掉不属于本表的数据
		$fields = $dao->info(Zend_Db_Table_Abstract::COLS);
		foreach ($data as $key => $value) {
			if (! in_array($key, $fields)) {
				unset($data[$key]);
			}
		}
		//设置主键字段的检索条件
		$pk = $this->getPk();
		foreach ($data as $key => $value) {
			if (in_array($key,$pk)) {
				$selector->where($adapter->quoteInto("$key=?",$value));
			}
		}
		
		$where = implode(' ', $selector->getPart('where'));
		return $dao->update($data, $where);
	}
	
	
	/**
	 * delete by primary key
	 * 
	 * @param array $keys
	 * @return int The number of rows deleted.
	 */
	public function delete(array $keys)
	{
		$dao = $this->getDao();
		$adapter = $dao ->getAdapter();
		$selector = $dao->select();
		
		//设置主键字段的检索条件
		$pk = $this->getPk();
		foreach ($keys as $key => $value) {
			if (in_array($key,$pk)) {
				$selector->where($adapter->quoteInto("$key=?",$value));
			}
		}
		
		$where = implode(' ', $selector->getPart('where'));
		return $dao->delete($where);
	}
	
	/**
	 * delete by condition
	 *
	 * @param string condition
	 * @return int The number of rows deleted.
	 */
	public function deleteBy($condition)
	{
		$dao = $this->getDao();
		return $dao->delete($condition);
	}
	
	/**
	 * fetch all
	 * 
	 * @param int $pageIndex
	 * @param int $pageNum
	 * @param string $where
	 * @param array $order
	 * @param string $group
	 * @param string $fields
	 * @return array rows
	 */
	public function fetchAll($pageIndex = 1, $pageNum = 20, $where = null, $order = null , $group = null, $fields = null)
	{
		$dao = $this->getDao();
		$selector = $dao->select();
		if (!empty($where) and strlen($where)>0) $selector->where($where);
		if (!empty($order)) $selector->order($order);
		if (!empty($group)) 	$selector->group($group);
		if (!empty($fields)) 	$selector->from($dao->info(Zend_Db_Table_Abstract::NAME),$fields);
		$selector->limit($pageNum,($pageIndex -1) * $pageNum);
		return $dao->fetchAll($selector)->toArray();
	}
	
	/**
	 * fetch limit
	 *
	 * @param int $rowStart
	 * @param int $rowEnd
	 * @param string $where
	 * @param array $order
	 * @return array rows
	 * modify by vincent
	 */
	public function fetchLimit($rowStart = 0, $rowEnd = 0, $where = null, $order = null)
	{
		$dao = $this->getDao();
		$selector = $dao->select();
		if(strlen($where)>0)
			$selector->where($where);
		//if(strlen($order)>0)
		$selector->order($order);
		$selector->limit($rowEnd,$rowStart);
		return $dao->fetchAll($selector)->toArray();
	}
	
	/**
	 * get count by conditions
	 * 
	 * @param string $condition
	 * @return int The Number of Rows
	 */
	public function getCount($condition = null,$group = null)
	{
		$dao = $this->getDao();
		$ad = $dao->getAdapter();
		$tableName = $dao->info(Zend_Db_Table_Abstract::NAME);
		if($condition === null) {
			return $ad->fetchOne("select count(*) from $tableName");
		} else {
			if($group){//by vincent
				return $ad->fetchOne(sprintf("select count(%s) from (select %s from %s where %s GROUP BY %s) as tp",$group,$group,$tableName,$condition,$group));
			}else{
				return $ad->fetchOne("select count(*) from $tableName where ". $condition);
			}
		}			
	}
	
	/**
	 * find by primary key 
	 * 
	 * @param array $keys
	 * @return row
	 */
	public function find(array $keys)
	{
		$dao = $this->getDao();
		$adapter = $dao ->getAdapter();
		$selector = $dao->select();
		
		//设置主键字段的检索条件
		$pk = $this->getPk();
		foreach ($keys as $key => $value) {
			if (in_array($key,$pk)) {
				$selector->where($adapter->quoteInto("$key=?",$value)); 	
			}
		}

		return $dao->fetchRow($selector);
		
	}
	
	/**
	 * find by $where
	 *
	 * @param string $where
	 * @param array $order
	 * @param array $fields
	 * @return Zend_Db_Table_Row_Abstract
	 */
	public function findBy($where, $order = null, $fields = null)
	{
		$dao = $this->getDao();
		$adapter = $dao ->getAdapter();
		$tableName = $dao->info(Zend_Db_Table_Abstract::NAME);
		$selector = $dao->select();
		$selector->where($where);
		$selector->order($order);
		if (!empty($fields)) {
			$selector->from($tableName,$fields);
		}
		return $dao->fetchRow($selector);
	}
	
	/**
	 * sum column by conditions
	 *
	 * @param string $column
	 * @param string $condition
	 * @return int sum of column
	 */
	public function getSumByColumn($column, $condition = null)
	{
		$dao = $this->getDao();
		$ad = $dao->getAdapter();
		$tableName = $dao->info(Zend_Db_Table_Abstract::NAME);		
		if($condition === null) {
			return $ad->fetchOne("select sum($column) from $tableName");
		} else {
			return $ad->fetchOne("select sum($column) from $tableName where ". $condition);
		}
	}
	
	/**
	 * querySQL语句
	 * @param string $sql
	 * @return array mixed data return an array containing all of the result set rows
	 */
	public function __querySQL($sql)
	{
		//获得db对象
		$dao = $this->getDao();
		$db = $dao->getAdapter();
		
		//准备statement
		$stmt = $db->query($sql);
		
		//使用PDOStatement对象$stmt将所有结果数据放到一个数组$result中，并返回$result
		$result = $stmt->fetchAll();
		return $result;
	}
	
	/**
	 * insertSQL语句
	 * @param array $row
	 * @example 以"列名"=>"数据"的格式格式构造插入数组,插入数据行
     *         $row = array (
     *              'noble_title'    => 'King',
     *              'first_name'     => 'Arthur',
     *              'favorite_color' => 'blue',
     *          );
     * @return number
	 */
	public function __insertSQL($row)
	{
		//获得db对象
		$dao = $this->getDao();
		$db = $dao->getAdapter();
		
		//插入数据的数据表
		$tableName = $dao->info(Zend_Db_Table_Abstract::NAME);
		
		//插入数据行并返回行数
		$rows_affected = $db->insert($tableName, $row);
		$last_insert_id = $db->lastInsertId();
		return $last_insert_id;
		
	}
	
	/**
	 * udpateSQL语句
	 * 
	 * @param array $row
	 * @example 以"列名"=>"数据"的格式格式构造插入数组,插入数据行
     *         $row = array (
     *              'noble_title'    => 'King',
     *              'first_name'     => 'Arthur',
     *              'favorite_color' => 'blue',
     *          );
	 * @param string $where
	 * @return number
	 */
	public function __updateSQL($row, $where)
	{
		//获得db对象
		$dao = $this->getDao();
		$db = $dao->getAdapter();
		
		//插入数据的数据表
		$tableName = $dao->info(Zend_Db_Table_Abstract::NAME);
		
		//更新表数据,返回更新的行数
		$rows_affected = $db->update($tableName, $row, $where);
		return $rows_affected;
	}
	
	/**
	 * deleteSQL语句
	 * 
	 * @param string $where
	 * @return number
	 */
	public function __deleteSQL($where)
	{
		//获得db对象
		$dao = $this->getDao();
		$db = $dao->getAdapter();
		
		//插入数据的数据表
		$tableName = $dao->info(Zend_Db_Table_Abstract::NAME);
		
		//更新表数据,返回更新的行数
		$rows_affected = $db->delete($tableName, $where);
		return $rows_affected;
	}
	
	/**
	 * 执行sql语句
	 * @param string $sql
	 * @return bool Returns true on success or false on failure.
	 */
	public function __execSQL($sql)
	{
		//获得db对象
		$dao = $this->getDao();
		$db = $dao->getAdapter();
	
		//准备statement
		$stmt = $db->prepare($sql);
	
		//执行statement
		$result = $stmt->execute();
		return $result;
	}
}